package com.common.android.ui.gif;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.ref.WeakReference;

import com.common.android.ui.gif.GifDecoder.BitmapDecodeCallback;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.ImageView;


public class GifImageView extends ImageView {
	private static final String TAG = "GifImageView";
	private DecodeThread mDecodeThread;
	private boolean mbIsScaled=false;
	private int mResId = 0;
	private File mFile;
	private Bitmap mLastBitmap;
	private Object mKey;
	public GifImageView(Context context) {
		super(context);
	}
	
	public GifImageView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public GifImageView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}
	
	public void setGifImage(String filePath) throws FileNotFoundException {
		if (TextUtils.isEmpty(filePath)) {
			return;
		}
		checkDuplicate();
		mKey=filePath;
		mFile = new File(filePath);
		startDecodeThread();
	}

	public void setGifImage(int resId) {
		checkDuplicate();
		mResId = resId;
		mKey=resId;
		startDecodeThread();
	}

	private void checkDuplicate() {
		// one view with one InputStream to make simple
		if (mDecodeThread != null) {
			throw new IllegalStateException("View can't be reused");
		}
	}

	public synchronized void startDecodeThread() {
		if (mDecodeThread == null
				|| (mDecodeThread != null && mDecodeThread.mIsQuit)) {
			mDecodeThread = new DecodeThread();
			mDecodeThread.start();
		}
	}

	private static class DrawHandler extends Handler {

		WeakReference<GifImageView> mWGImageView;

		public DrawHandler(GifImageView view) {
			mWGImageView = new WeakReference<GifImageView>(view);
		}

		@Override
		public void handleMessage(Message msg) {
			GifImageView giv = mWGImageView.get();
			if (giv != null) {
				if (msg.obj instanceof Bitmap) {
					Bitmap bmp = (Bitmap) msg.obj;
					try {
						if(bmp.isRecycled()){
							return;
						}
						//modify by chenqsh 2014-1-23
						giv.drawImage(bmp);
						updateBaseMatrix(giv);
					} catch (Exception e) {
						
					}
				}
			}
		}
	}

	//add by chenqsh 2014-1-23
	public static Matrix matrix = new Matrix();
	private static void updateBaseMatrix(ImageView imageView) {
		if (null == imageView) {
			return;
		}
		Drawable d = imageView.getDrawable();
		if (d == null) {
			return;
		}
		matrix.reset();
		final float viewWidth = imageView.getWidth();
		final float viewHeight = imageView.getHeight();
		final int drawableWidth = d.getIntrinsicWidth();
		final int drawableHeight = d.getIntrinsicHeight();

		final float widthScale = viewWidth / drawableWidth;
		final float heightScale = viewHeight / drawableHeight;
		float scale = Math.min(2.0f, Math.min(widthScale, heightScale));
		matrix.postScale(scale, scale);
		matrix.postTranslate((viewWidth - drawableWidth * scale) / 2F,
				(viewHeight - drawableHeight * scale) / 2F);
		imageView.setImageMatrix(matrix);
	}
	public void quit() {
		if (mDecodeThread != null) {
			mDecodeThread.quit();
		}
//		recycle();
	}

	private Handler drawHandler = new DrawHandler(this);

	private void drawImage(Bitmap currentImage) {
		if (currentImage.isRecycled()) {
			return;
		}
		
		//Bitmap scale=getScaleBitmap(currentImage);
		//		setImageBitmap(scale);
		setImageBitmap(currentImage);
		invalidate();
		if (mLastBitmap != null) { // 回收上一帧图片
			mLastBitmap.recycle();
//			mLastBitmap = null;
		}
		//mLastBitmap = scale;
		mLastBitmap = currentImage;
	}
	
	private Bitmap getScaleBitmap(Bitmap last){
		if (mbIsScaled || last==null){
			return last;
		}else{
			int w=last.getWidth();
			int h=last.getHeight();
			return Bitmap.createScaledBitmap(last, last.getWidth()*2, last.getHeight()*2, true);
		}
	}

	private class DecodeThread extends Thread {
		private long mLastDecodedTime;

		boolean mIsQuit = false; // 用户离开界面

		@Override
		public void run() {
			int status = GifDecoder.STATUS_OK;
			// loop to show GIF image
			while (status == GifDecoder.STATUS_OK && !mIsQuit) {
				// initial InputStream from kinds of resource
				InputStream is = null;
				if (mResId != 0) {
					is = GifImageView.this.getContext().getResources()
							.openRawResource(mResId);
				} else if (mFile != null) {
					try {
						is = new FileInputStream(mFile);
					} catch (FileNotFoundException e) {
						e.printStackTrace();
						return;
					}
				}
				if (is != null) {
					// decode
					status = play(is);
				} else {
					return;
				}
			}
		}

		public void quit() {
			mIsQuit = true;
		}

		/**
		 * The key code
		 * 
		 * @param stream
		 * @return the status code
		 */
		private int play(final InputStream stream) {
			final GifDecoder mGifDecoder = new GifDecoder();
			// Log.i(TAG, "start to decode");
			mLastDecodedTime = 0;
			mGifDecoder.setBitmapDecodeCallback(new BitmapDecodeCallback() {

				@Override
				public void onDecoded(Bitmap bmp, int lastDelay) {
					if (mIsQuit) {
						//停止继续解析下一帧
						mGifDecoder.quit();
						//如果不注掉下面这句代码,退到后台会崩溃,原因是使用了被RECYLE的图片.所以只能这边不回收,在下面增加一个RECYCLE方法来等界面销毁的时候来回收图片
						//bmp.recycle();
						Message msg = drawHandler.obtainMessage();
						msg.obj = bmp;
						drawHandler.sendMessage(msg);
						return;
					}

					long now = System.currentTimeMillis();
					if (mLastDecodedTime > 0) { // 计算这一帧的图片是否应该延迟展示
						long delayed = now - mLastDecodedTime;
						// Log.i(TAG, "delayed: " + delayed);
						if (delayed > 0 && lastDelay > 0 && delayed < lastDelay) {
							long needMoreTime = lastDelay - delayed;
							// Log.i(TAG, "going to sleep for more time: " +
							// needMoreTime);
							try {
								Thread.sleep(needMoreTime);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
					mLastDecodedTime = System.currentTimeMillis();
						Message msg = drawHandler.obtainMessage();
						msg.obj = bmp;
						drawHandler.sendMessage(msg);
				}
			});

			int ostatus = GifDecoder.STATUS_OK;
			try {
				ostatus = mGifDecoder.read(stream);
			} catch (java.lang.OutOfMemoryError e) {
				return ostatus;
			} catch (Exception e) {
				return ostatus;
			}

			if (ostatus != GifDecoder.STATUS_OK) {
			}else{
				if (isSaveFrames){
					GifCacheManager.INSTANCE.notifyDeocdeResult(mKey, "");
					isSaveFrames=false;
				}
			}
			return ostatus;
		}
	}

	public void recycle(){
		if (mLastBitmap!=null){
			mLastBitmap.recycle();
			mLastBitmap = null;
		}
	}
	
	public void changeScale(){
		mbIsScaled=!mbIsScaled;
	}
	
	private boolean isSaveFrames=false;
	public void setSaveFrames(){
		isSaveFrames=true;
	}
}
